// context.ts
import type { TypedKey } from './types';

export function createTypedKey<T>(key: string, defaultValue: T): TypedKey<T> {
  return { key, defaultValue };
}

export class Context {
  private data: Record<string, unknown>;
  private listeners: Record<string, Array<(newValue: unknown) => void>> = {};

  constructor(initialValue: Record<string, unknown> = {}) {
    this.data = { ...initialValue };
  }

  getData<T>(key: TypedKey<T>): T {
    if (!(key.key in this.data)) {
      this.data[key.key] = key.defaultValue;
    }
    return this.data[key.key] as T;
  }

  setData<T>(key: TypedKey<T>, value: T): void {
    this.data[key.key] = value;
    this.notifyListeners(key.key, value);
  }

  subscribe<T>(key: TypedKey<T>, listener: (newValue: T) => void): () => void {
    const keyStr = key.key;
    if (!this.listeners[keyStr]) {
      this.listeners[keyStr] = [];
    }
    this.listeners[keyStr].push(listener as (newValue: unknown) => void);
    return () => {
      this.listeners[keyStr] = this.listeners[keyStr].filter(
        (l) => l !== listener,
      );
    };
  }

  private notifyListeners(key: string, newValue: unknown): void {
    if (this.listeners[key]) {
      this.listeners[key].forEach((listener) => listener(newValue));
    }
  }
}
